#include "stdafx.h"
#include "NetCard.h"

ITypeInfo *NetCardTypeInfo;

HRESULT LoadNetCardTypeInfo()
{
    HRESULT hr;
    ITypeLib *pTypeLib = NULL;
    hr = LoadRegTypeLib(TLBID_IExample, 1, 0, 0, &pTypeLib);
    if (FAILED(hr)) return hr;
    hr = pTypeLib->GetTypeInfoOfGuid(IID_INetCard, &NetCardTypeInfo);
    pTypeLib->Release();
    if (FAILED(hr)) return hr;
    NetCardTypeInfo->AddRef();
    return S_OK;
}

NetCard::NetCard() : m_count(1), m_name(NULL), m_address(NULL)
{
}

NetCard::~NetCard()
{
    SysFreeString(m_name);
    SysFreeString(m_address);
}

HRESULT STDMETHODCALLTYPE NetCard::QueryInterface(REFIID riid, void **ppv)
{
    if (IsEqualIID(riid, IID_IUnknown) ||
        IsEqualIID(riid, IID_IDispatch) ||
        IsEqualIID(riid, IID_INetCard))
    {
        *ppv = this;
        AddRef();
        return S_OK;
    }

    *ppv = NULL;
    return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE NetCard::AddRef()
{
    return ++m_count;
}

ULONG STDMETHODCALLTYPE NetCard::Release()
{
    if (--m_count == 0)
    {
        delete this;
        InterlockedDecrement(&OutstandingObjects);
        return 0;
    }
    return m_count;
}

HRESULT STDMETHODCALLTYPE NetCard::GetTypeInfoCount(UINT *pctinfo)
{
    *pctinfo = 1;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE NetCard::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
    *ppTInfo = NULL;
    if (iTInfo != 0) return DISP_E_BADINDEX;
    if (NetCardTypeInfo != NULL)
    {
        NetCardTypeInfo->AddRef();
    }
    else
    {
        HRESULT hr = LoadNetCardTypeInfo();
        if (FAILED(hr)) return hr;
    }
    *ppTInfo = NetCardTypeInfo;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE NetCard::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
    if (NetCardTypeInfo == NULL)
    {
        HRESULT hr = LoadNetCardTypeInfo();
        if (FAILED(hr)) return hr;
    }
    return DispGetIDsOfNames(NetCardTypeInfo, rgszNames, cNames, rgDispId);
}

HRESULT STDMETHODCALLTYPE NetCard::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
                                          WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
                                          EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
    if (!IsEqualIID(riid, IID_NULL)) return DISP_E_UNKNOWNINTERFACE;
    if (NetCardTypeInfo == NULL)
    {
        HRESULT hr = LoadNetCardTypeInfo();
        if (FAILED(hr)) return hr;
    }
    return DispInvoke(this, NetCardTypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}

HRESULT STDMETHODCALLTYPE NetCard::GetName(BSTR *str)
{
    if (str == NULL) return E_POINTER;
    *str = SysAllocStringLen(m_name, SysStringLen(m_name));
    if (*str == NULL) return E_OUTOFMEMORY;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE NetCard::GetAddress(BSTR *str)
{
    if (str == NULL) return E_POINTER;
    *str = SysAllocStringLen(m_address, SysStringLen(m_address));
    if (*str == NULL) return E_OUTOFMEMORY;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE NetCard::SetName(BSTR str)
{
    if (str == NULL) return E_POINTER;
    if (m_name) SysFreeString(m_name);
    m_name = SysAllocString(str);
    if (m_name == NULL) return E_OUTOFMEMORY;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE NetCard::SetAddress(BSTR str)
{
    if (str == NULL) return E_POINTER;
    if (m_address) SysFreeString(m_address);
    m_address = SysAllocString(str);
    if (m_address == NULL) return E_OUTOFMEMORY;
    return S_OK;
}
